package github.saukiya.sxattribute.util.nms;

import com.google.common.collect.HashMultimap;
import com.mysql.fabric.xmlrpc.base.Array;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author Saukiya
 */

@Getter
public abstract class NMSBase implements BukkitVersion {

    protected Class<?> xCraftItemStack;
    protected Class<?> xNBTTagCompound;
    protected Class<?> xNBTTagList;
    protected Constructor<?> xNewNBTTagString;
    protected Constructor<?> xNewNBTTagDouble;
    protected Constructor<?> xNewNBTTagInt;

    protected Method xAsNMSCopay;
    protected Method xGetTag;
    protected Method xHasTag;
    protected Method xSet;
    protected Method xAdd;
    protected Method xRemove;
    protected Method xSetTag;
    protected Method xAsBukkitCopy;

    protected Method xHasKey;
    protected Method xGet;
    protected Method xGetString;
    protected Method xGetListString;
    protected Method xSize;

    private Map<EquipmentSlot,List<String>> equipmentSlotListHashMap = new HashMap<>();

    /**
     * 加载NBT反射类
     * 此类所附加的nbt均带有插件名
     *
     * @throws NoSuchMethodException  NoSuchMethodException
     * @throws ClassNotFoundException ClassNotFoundException
     */
    public NMSBase() throws Exception {
        equipmentSlotListHashMap.put(EquipmentSlot.HAND, Arrays.asList(
                "_SHOVE","_PICKAXE","_AXE","_HOE","TRIDENT","SWORD"
        ));
        equipmentSlotListHashMap.put(EquipmentSlot.HEAD,Arrays.asList(
                "_HELMET"
        ));
        equipmentSlotListHashMap.put(EquipmentSlot.CHEST,Arrays.asList(
                "_CHEST"
        ));

        equipmentSlotListHashMap.put(EquipmentSlot.LEGS,Arrays.asList(
                "_LEG"
        ));

        equipmentSlotListHashMap.put(EquipmentSlot.FEET,Arrays.asList(
                "_BOOT"
        ));
    }

    public EquipmentSlot getSlot(Material material){
        for (Map.Entry<EquipmentSlot, List<String>> equipmentSlotListEntry : equipmentSlotListHashMap.entrySet()) {
            for (String s : equipmentSlotListEntry.getValue()) {
                if (material.name().endsWith(s) || material.name().contains(s)){
                    return equipmentSlotListEntry.getKey();
                }
            }
        }
        return null;
    }

    public Attribute getAttributeEnum(Material material){
        EquipmentSlot equipmentSlot = getSlot(material);
        if (equipmentSlot != null){
            return getAttributeEnum(equipmentSlot);
        }
        return null;
    }

    public Attribute getAttributeEnum(EquipmentSlot equipmentSlot){
        switch (equipmentSlot) {
            case HEAD:
            case FEET:
            case LEGS:
            case CHEST:
                return Attribute.GENERIC_ARMOR;
            case HAND:
                return Attribute.GENERIC_ATTACK_DAMAGE;
        }
        return null;
    }

    public HashMultimap<Attribute,AttributeModifier> defaultModifier(EquipmentSlot equipmentSlot){
        HashMultimap<Attribute,AttributeModifier> attributeAttributeModifierHashMultimap = HashMultimap.create();
        //攻击
        AttributeModifier modifier = new AttributeModifier(
                UUID.randomUUID(),
                "a",
                0,
                AttributeModifier.Operation.ADD_NUMBER,
                equipmentSlot
        );
        return attributeAttributeModifierHashMultimap;
    }

    public abstract ItemStack updateAttack(ItemStack item,double speed);

    /**
     * 清除物品默认属性标签
     *
     * @param item ItemStack
     */
    public abstract ItemStack clearAttribute(ItemStack item);

    /**
     * 获取全部NBT数据
     *
     * @param item ItemStack
     * @return String
     */
    public abstract String getAllNBT(ItemStack item);

    /**
     * 设置物品NBT数据
     *
     * @param item  ItemStack
     * @param key   String
     * @param value String
     * @return ItemStack
     */
    public abstract ItemStack setNBT(ItemStack item, String key, Object value);

    /**
     * 设置物品NBT数据 List 会被设置ItemMeta
     *
     * @param item ItemStack
     * @param key  String
     * @param list List
     * @return ItemStack
     */
    public abstract ItemStack setNBTList(ItemStack item, String key, List<String> list);

    /**
     * 获取物品NBT数据
     *
     * @param item ItemStack
     * @param key  String
     * @return String
     */
    public abstract String getNBT(ItemStack item, String key);


    /**
     * 设置物品NBT数据 List
     *
     * @param item ItemStack
     * @param key  String
     * @return List
     */
    public abstract List<String> getNBTList(ItemStack item, String key);

    /**
     * 判断是否有物品NBT数据
     *
     * @param item ItemStack
     * @param key  String
     * @return Boolean
     */
    public abstract boolean hasNBT(ItemStack item, String key);



    /**
     * 清除指定nbt
     *
     * @param item ItemStack
     * @param key  String
     * @return boolean
     */
    public abstract boolean removeNBT(ItemStack item, String key);

    public abstract void invoke(Method method,Object o,Object... objects);

    public Class<?> getNMSClass(String name) throws Exception{
        return Class.forName("net.minecraft.server."+NMSUtils.getVersion()+"."+name);
    }
}
